package util.dataEncrype;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.util.Random;

//@Slf4j
public class EncryptUtil {

	public static String md5(String str) {
		str = str == null ? StringUtils.EMPTY : str;
		try {
			MessageDigest md5 = MessageDigest.getInstance("MD5");
			return Base64.encodeBase64String(md5.digest(str.getBytes("UTF-8")));
		} catch (Exception e) {
//			log.error("encrypt {} error", e);
			return str;
		}
	}

	private static Random RANDOM = new Random();

	// 加密的key，不能重复
	private static final String SECRET_KEY = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
	// 27进制数表示
	private static final String HEX_KEY = "0123456789abcdefghijklmnopq";

	private static final int RADIX = HEX_KEY.length();

	public static String encrypt(Long num) {
		if (num == null) {
			return StringUtils.EMPTY;
		}
		try {
			return doEncrypt(num);
		} catch (Exception e) {
//			log.error("encrypt {} error,", num, e);
			return null;
		}
	}

	public static Long decrypt(String str) {
		if (StringUtils.isBlank(str)) {
			return null;
		}
		try {
			return doDecrypt(str);
		} catch (Exception e) {
//			log.error("decrypt {} error,", str, e);
			return null;
		}
	}

	public static String doEncrypt(Long num) {
		StringBuilder result = new StringBuilder();

		int keyLength = SECRET_KEY.length();
		String numStr = Long.toString(num, RADIX);
		int randomIndex = RANDOM.nextInt(keyLength);

		for (int i = 0; i < numStr.length(); i++) {
			char c = SECRET_KEY.charAt((HEX_KEY.indexOf(numStr.charAt(i)) + randomIndex) % keyLength);
			result.append(c);
		}

		while (result.length() < 8) {
			result.append(SECRET_KEY.charAt(RANDOM.nextInt(keyLength)));
		}

		result.append(getLengthChar(numStr, randomIndex));
		result.append(SECRET_KEY.charAt(randomIndex));

		return result.toString();
	}

	public static Long doDecrypt(String str) {
		StringBuilder num = new StringBuilder();

		int keyLength = SECRET_KEY.length();
		int randomIndex = SECRET_KEY.indexOf(str.charAt(str.length() - 1));
		int charLength = getOrig(str.charAt(str.length() - 2), randomIndex);
		for (int i = 0; i < charLength; i++) {
			int orig = SECRET_KEY.indexOf(str.charAt(i));
			orig = orig - randomIndex;
			if (orig < 0) {
				orig = orig + keyLength;
			}

			num.append(HEX_KEY.charAt(orig));
		}
		return Long.parseLong(num.toString(), RADIX);
	}

	private static char getLengthChar(String str, int random) {
		return SECRET_KEY.charAt((str.length() + random) % SECRET_KEY.length());
	}

	private static int getOrig(char secretChar, int random) {
		int num = SECRET_KEY.indexOf(secretChar);
		num = num - random;
		if (num < 0) {
			num = num + SECRET_KEY.length();
		}
		return num;
	}

	private static String DES_SECRET_KEY = "abcdef0123456789";
	private static String IV_PARAMETER = "0123456789abcdef";

	public static String encryptText(String sourceStr) {
		try {
			Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
			byte[] raw = DES_SECRET_KEY.getBytes();
			SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
			IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes());
			cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
			byte[] encrypted = cipher.doFinal(sourceStr.getBytes("utf-8"));

			return Base64.encodeBase64String(encrypted);
		} catch (Exception e) {
//			log.error("encryptText {} error,", sourceStr, e);
			return StringUtils.EMPTY;
		}
	}

	public static String decryptText(String encryptedStr) {
		try {
			byte[] encryptedBase64 = Base64.decodeBase64(encryptedStr);

			byte[] raw = DES_SECRET_KEY.getBytes("ASCII");
			SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
			Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
			IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes());
			cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

			byte[] original = cipher.doFinal(encryptedBase64);

			return new String(original, "utf-8");
		} catch (Exception ex) {
//			log.error("decryptText {} error,", encryptedStr, ex);
			return null;
		}
	}

	public static String toHexString1(byte[] b){
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < b.length; ++i){
			buffer.append(toHexString1(b[i]));
		}
		return buffer.toString();
	}
	public static String toHexString1(byte b){
		String s = Integer.toHexString(b & 0xFF);
		if (s.length() == 1){
			return "0" + s;
		}else{
			return s;
		}
	}
	public static void main(String[] args) throws  Exception {

		String s = md5("123456");
		System.out.print(s+" ");

		// s = encrypt(123L);
		// System.out.print(s+" ");
		// System.out.println(decrypt(s));

	}
}
